home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / coral / coral.c next >
C/C++ Source or Header  |  1995-05-03  |  21KB  |  690 lines

  1. /*
  2.  *    @(#) coral.c 1.3 93/11/02 MRINC
  3.  *
  4.  *    Written using CGI 10 Jun 1987 by Ron Record (rr@sco.com)
  5.  *    Rewritten using X11 06 Apr 1993 by Ron Record (rr@sco.com)
  6.  */
  7. /*************************************************************************
  8.  *                                                                       *
  9.  *  Copyright (c) 1987-1993 Ronald Joe Record                            *
  10.  *                                                                       *
  11.  *  All rights reserved. No part of this program or publication may be   *
  12.  *  reproduced, transmitted, transcribed, stored in a retrieval system,  *
  13.  *  or translated into any language or computer language, in any form or *
  14.  *  by any means, electronic, mechanical, magnetic, optical, chemical,   *
  15.  *  biological, or otherwise, without the prior written permission of:   *
  16.  *                                                                       *
  17.  *      Ronald Joe Record (408) 458-3718                                 *
  18.  *      212 Owen St., Santa Cruz, California 95062 USA                   *
  19.  *                                                                       *
  20.  *************************************************************************/
  21.  
  22.  
  23. #include "coral.h"
  24.  
  25. int col_duration = 0;
  26. int now_x, now_y, max_y;
  27. int width, height;
  28. int nballs = 16;
  29. int coral_hue, count;
  30. int nummaps=1, delay=0;
  31. int demo=0, useroot=0, full=0, oflag=0, spin=0;
  32. int maxcolor, next;
  33. int **xy;
  34. char *outname;
  35.  
  36. extern long lrand48();
  37. extern void BufferPoint(), InitBuffer(), FlushBuffer();
  38.  
  39. void
  40. usage()
  41. {
  42.     printf("Usage: coral [-o file][-dsuFRTV]");
  43.     printf("[-m #][-w width][-h height]\n");
  44.     printf("\t-d indicates demo mode\n");
  45.     printf("\t-s indicates spin color wheel when done computing\n");
  46.     printf("\t-R indicates use the root window\n");
  47.     printf("\t-m # indicates a minimum color index of # (0-255)\n");
  48.     printf("\t-o file will save the output as 'file' in PPM format\n");
  49.     printf("\t-w # indicates a window width of #\n");
  50.     printf("\t-h # indicates a window height of #\n");
  51.     printf("\t-u produces this message\n");
  52.     printf("During display :\n");
  53.     printf("\t'f' or 'F' will save the picture as a PPM file\n");
  54.     printf("\t'+' will increment and '-' decrement the minimum color index\n");
  55.     printf("\t'r' or 's' will spin the color wheel forwards or backwards\n");
  56.     printf("\t'W' will increment and 'w' decrement the color map selection\n");
  57.     printf("\t'?' or 'h' will display the usage message\n");
  58.     printf("\t'q' or 'Q' will quit\n");
  59. }
  60.  
  61. void
  62. init_contexts()
  63. {
  64.     static int i;
  65.  
  66.     /*
  67.      * create default, writable, graphics contexts for the canvas.
  68.      */
  69.     Data_GC[0] = XCreateGC(dpy, DefaultRootWindow(dpy),
  70.         (unsigned long) NULL, (XGCValues *) NULL);
  71.     /* set the background to black */
  72.     XSetBackground(dpy,Data_GC[0],BlackPixel(dpy, screen));
  73.     /* set the foreground of the 0th context to black */
  74.     XSetForeground(dpy, Data_GC[0], BlackPixel(dpy, screen));
  75.     Data_GC[1] = XCreateGC(dpy, DefaultRootWindow(dpy),
  76.         (unsigned long) NULL, (XGCValues *) NULL);
  77.     /* set the background to black */
  78.     XSetBackground(dpy,Data_GC[1],BlackPixel(dpy, screen));
  79.     /* set the foreground of the 1st context to white */
  80.     XSetForeground(dpy, Data_GC[1], WhitePixel(dpy,  screen));
  81.     for (i=2; i<maxcolor; i++) {
  82.         Data_GC[i] = XCreateGC(dpy, DefaultRootWindow(dpy),
  83.             (unsigned long) NULL, (XGCValues *) NULL);
  84.         /* set the background to black */
  85.         XSetBackground(dpy,Data_GC[i],BlackPixel(dpy, screen));
  86.         /* set the foreground of the ith context to i */
  87.         XSetForeground(dpy, Data_GC[i], i);
  88.     }
  89. }
  90.  
  91. void
  92. Clear()
  93. {
  94.     XFillRectangle(dpy, pixmap, Data_GC[0], 0, 0, width, height);
  95.     XCopyArea(dpy, pixmap, canvas, Data_GC[0], 0, 0, width, height, 0, 0);
  96. }
  97.  
  98. void
  99. freemem()
  100. {
  101.     static int i;
  102.  
  103.     for (i=0;i<=width;i++)
  104.         free(xy[i]);
  105.     free(xy);
  106. }
  107.  
  108. void
  109. setupmem()
  110. {
  111.     static int i;
  112.  
  113.     if ((xy=(int **)malloc((width+1)*sizeof(int *))) == (int **)NULL) {
  114.         printf("Error malloc'ing xy.\n");
  115.         exit (-1);
  116.     }
  117.     for (i=0;i<width+1;i++) {
  118.         if ((xy[i]=(int *)malloc(height*sizeof(int)))==(int *)NULL){
  119.             printf("Error malloc'ing xy[%d].\n", i);
  120.             exit (-1);
  121.         }
  122.     }
  123. }
  124.  
  125. void
  126. init_pts()
  127. {
  128.     static int i, j;
  129.     static int initial_x, initial_y;
  130.  
  131.     for (i=0; i<width+1; i++)
  132.         for (j=0; j<height; j++)
  133.             xy[i][j] = 0;
  134.     max_y = 2;
  135.     initial_y = 0;
  136.     for (j=0;j<nballs;j++) {
  137.         initial_x = ((int)lrand48() % (width-2)) + 1;
  138.         xy[initial_x][initial_y] = coral_hue;
  139.         BufferPoint(dpy, canvas, pixmap, Data_GC, &Points, coral_hue, 
  140.                     initial_x, height - initial_y - 1);
  141.     }
  142.     FlushBuffer(dpy,canvas,pixmap,Data_GC,&Points,coral_hue,coral_hue+1);
  143.     count = nballs;
  144. }
  145.  
  146. #define x_str 10
  147.  
  148. void
  149. print_help() 
  150. {
  151.     static char str[80];
  152.     static int y_str, spacing;
  153.     static int ascent, descent, dir;
  154.     static XCharStruct overall;
  155.     static GC gc;
  156.  
  157.     gc = Data_GC[1];
  158.     XClearWindow(dpy, help);
  159.     y_str = 60;
  160.     sprintf(str,"During run-time, interactive control can be exerted via : ");
  161.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  162.     XQueryTextExtents(dpy,(XID)XGContextFromGC(gc),"Hey!",
  163.             4,&dir,&ascent,&descent,&overall);
  164.     spacing = ascent + descent + 5;
  165.     y_str += 2 * spacing;
  166.     sprintf(str,"        - lowers the value of mincolindex, + raises it");
  167.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  168.     y_str += spacing;
  169.     sprintf(str,"        f or F saves coral to a PPM file");
  170.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  171.     y_str += spacing;
  172.     sprintf(str,"        h or H or ? displays this message");
  173.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  174.     y_str += spacing;
  175.     sprintf(str,"        n goes on to the next coral");
  176.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  177.     y_str += spacing;
  178.     sprintf(str,"        N creates a new replacement coral");
  179.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  180.     y_str += spacing;
  181.     sprintf(str,"        r or s spins the colorwheel");
  182.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  183.     y_str += spacing;
  184.     sprintf(str,"        w decrements, W increments the color wheel index");
  185.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  186.     y_str += spacing;
  187.     sprintf(str,"        q or Q exits");
  188.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  189.     y_str += 2*spacing;
  190.     sprintf(str,"Press 'h', 'H', or '?' to unmap the help window");
  191.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  192. }
  193.  
  194. void
  195. redisplay (event)
  196. XExposeEvent    *event;
  197. {
  198.     if ((event->window == help) && (!useroot))
  199.         print_help();
  200.     else {
  201.         /*
  202.         * Extract the exposed area from the event and copy
  203.         * from the saved pixmap to the window.
  204.         */
  205.         XCopyArea(dpy, pixmap, canvas, Data_GC[0], event->x, event->y, 
  206.             event->width, event->height, event->x, event->y);
  207.     }
  208. }
  209.  
  210. void
  211. resize()
  212. {
  213.     Window r;
  214.     int j; 
  215.     int x, y;
  216.     unsigned int bw, d, new_w, new_h;
  217.     extern void Clear(), midpoint(), event_loop();
  218.  
  219.     freemem();
  220.     XGetGeometry(dpy,canvas,&r,&x,&y,&new_w,&new_h,&bw,&d);
  221.     if (((int)new_w == width) && ((int)new_h == height)) {
  222.         setupmem();
  223.         InitBuffer(&Points, maxcolor);
  224.         Clear();
  225.         init_pts();
  226.         return;
  227.     }
  228.     width = (int)new_w; height = (int)new_h;
  229.     if (pixmap)
  230.         XFreePixmap(dpy, pixmap);
  231.     pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), 
  232.             width, height, DefaultDepth(dpy, screen));
  233.     setupmem();
  234.     InitBuffer(&Points, maxcolor);
  235.     Clear();
  236.     init_pts();
  237.     FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  238. }
  239.  
  240. void
  241. Cleanup() {
  242.     freemem();
  243.     XCloseDisplay(dpy);
  244. }
  245.  
  246. /* Store coral growth in PPM format */
  247. void
  248. save()
  249. {
  250.     FILE *outfile;
  251.     unsigned char c;
  252.     XImage *ximage;
  253.     static int i,j;
  254.     struct Colormap {
  255.         unsigned char red;
  256.         unsigned char green;
  257.         unsigned char blue;
  258.     };
  259.     struct Colormap *colormap=NULL;
  260.  
  261.     if ((colormap=
  262.         (struct Colormap *)malloc(sizeof(struct Colormap)*maxcolor))
  263.             == NULL) {
  264.         fprintf(stderr,"Error malloc'ing colormap array\n");
  265.         Cleanup();
  266.         exit(-1);
  267.     }
  268.     outfile = fopen(outname,"w");
  269.     if(!outfile) {
  270.         perror(outname);
  271.         Cleanup();
  272.         exit(-1);
  273.     }
  274.  
  275.     ximage=XGetImage(dpy, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
  276.  
  277.     for (i=0;i<maxcolor;i++) {
  278.         colormap[i].red=(unsigned char)(Colors[i].red >> 8);
  279.         colormap[i].green=(unsigned char)(Colors[i].green >> 8);
  280.         colormap[i].blue =(unsigned char)(Colors[i].blue >> 8);
  281.     }
  282.     fprintf(outfile,"P%d %d %d\n",6,width,height);
  283.     fprintf(outfile,"%d\n",maxcolor-1);
  284.  
  285.     for (j=0;j<height;j++)
  286.         for (i=0;i<width;i++) {
  287.             c = (unsigned char)XGetPixel(ximage,i,j);
  288.             fwrite((char *)&colormap[c],sizeof colormap[0],1,outfile);
  289.         }
  290.     fclose(outfile);
  291.     free(colormap);
  292. }
  293.  
  294. void
  295. Redraw() {
  296.     static int i, j;
  297.     extern void event_loop();
  298.  
  299.     FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  300.     Clear();
  301.     for (i=0; i < width; i++)
  302.         for (j=0; j < height; j++)
  303.             if (xy[i][j])
  304.                 BufferPoint(dpy, canvas, pixmap, Data_GC, &Points, xy[i][j], 
  305.                             i, height - j - 1);
  306.     FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  307. }
  308.  
  309. void
  310. Getkey(event)
  311. XKeyEvent *event;
  312. {
  313.     char key;
  314.     static int spinning=0, spindir=0;
  315.     static XWindowAttributes attr;
  316.     extern void init_color(), write_cmap();
  317.  
  318.     if (XLookupString(event, (char *)&key, sizeof(key), (KeySym *)0,
  319.        (XComposeStatus *) 0) > 0)
  320.             switch (key) {
  321.                 case '\015': /*write out current colormap to $HOME/.<prog>map*/
  322.                     write_cmap(dpy,cmap,Colors,maxcolor,"coral","Coral");
  323.                     break;
  324.                 case '+': mincolindex += INDEXINC;
  325.                     if (mincolindex > maxcolor)
  326.                         mincolindex = 1;
  327.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  328.                             mincolindex,maxcolor,numwheels,"coral","Coral",0);
  329.                     break;
  330.                 case '-': mincolindex -= INDEXINC;
  331.                     if (mincolindex < 1)
  332.                         mincolindex = maxcolor - 1;
  333.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  334.                             mincolindex,maxcolor,numwheels,"coral","Coral",0);
  335.                     break;
  336.                 case 'd': delay -= 25; if (delay < 0) delay = 0; break;
  337.                 case 'D': delay += 25; break;
  338.                 case 'f':    /* save in PPM format file */
  339.                 case 'F': save(); break;
  340.                 case 'n':    /* go on to the next coral */
  341.                     next = 1;
  342.                     break;
  343.                 case 'N':    /* go on to the next coral */
  344.                     nummaps++;    /* but don't increment the coral counter */
  345.                     next = 1;
  346.                     break;
  347.                 case 'S':
  348.                 case 'R': spinning=0;
  349.                     break;
  350.                 case 'r': spinning=1; spindir=1; 
  351.                     Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 1);
  352.                     break;
  353.                 case 's': spinning=1; spindir=0;
  354.                     Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 0);
  355.                     break;
  356.                 case '\027': /* (ctrl-W) read palette from $HOME/.coralmap */
  357.                   numwheels = 0;
  358.                   init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  359.                             mincolindex,maxcolor,numwheels,"coral","Coral",0);
  360.                   break;
  361.                 case 'W': 
  362.                     if (numwheels < MAXWHEELS)
  363.                         numwheels++;
  364.                     else
  365.                         numwheels = 0;
  366.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  367.                             mincolindex,maxcolor,numwheels,"coral","Coral",0);
  368.                     break;
  369.                 case 'w': 
  370.                     if (numwheels > 0)
  371.                         numwheels--;
  372.                     else
  373.                         numwheels = MAXWHEELS;
  374.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  375.                             mincolindex,maxcolor,numwheels,"coral","Coral",0);
  376.                     break;
  377.                 case '?':
  378.                 case 'h': 
  379.                     if (!useroot) {
  380.                         XGetWindowAttributes(dpy, help, &attr);
  381.                         if (attr.map_state != IsUnmapped)
  382.                             XUnmapWindow(dpy, help);
  383.                         else {
  384.                             XMapRaised(dpy, help);
  385.                             print_help();
  386.                         }
  387.                     }
  388.                     break;
  389.                 case 'X':    /* restart coral growth with new seeds */
  390.                     FlushBuffer(dpy,canvas,pixmap,Data_GC,&Points,0,maxcolor);
  391.                     InitBuffer(&Points, maxcolor);
  392.                     Clear();
  393.                     init_pts();
  394.                     break;
  395.                 case 'Q':
  396.                 case 'q': Cleanup(); exit(0); break;
  397.             }
  398.             if (spinning)
  399.                 Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, spindir);
  400. }
  401.  
  402. void
  403. parseargs(argc, argv)
  404. int argc;
  405. char *argv[];
  406. {
  407.     int c;
  408.     extern int optind, getopt();
  409.     extern double atof();
  410.     extern char *optarg;
  411.  
  412.     outname = "coral.ppm";
  413.     width = 512; height = 480;
  414.     while((c = getopt(argc, argv, "dsuFRTVc:h:k:m:n:o:w:D:N:")) != EOF)
  415.     {    switch(c)
  416.         {
  417.         case 'c':
  418.             numwheels = atoi(optarg);
  419.             if (numwheels > MAXWHEELS)
  420.                 numwheels = MAXWHEELS;
  421.             if (numwheels < 0)
  422.                 numwheels = 0;
  423.             break;
  424.         case 'd':
  425.             demo++;
  426.             break;
  427.         case 'u':
  428.             usage();
  429.             exit(0);
  430.         case 'h':
  431.             height = atoi(optarg);
  432.             break;
  433.         case 'k':
  434.             col_duration = atoi(optarg);
  435.             break;
  436.         case 'm':
  437.             mincolindex = atoi(optarg);
  438.             break;
  439.         case 'n':
  440.             nummaps = atoi(optarg);
  441.             break;
  442.         case 'o':
  443.             ++oflag;
  444.             outname = optarg;
  445.             break;
  446.         case 's':
  447.             ++spin;
  448.             break;
  449.         case 'w':
  450.             width = atoi(optarg);
  451.             break;
  452.         case 'D':
  453.             delay = atoi(optarg);
  454.             break;
  455.         case 'F':
  456.             full++;
  457.             break;
  458.         case 'N':
  459.             nballs = atoi(optarg);
  460.             break;
  461.         case 'R':
  462.             useroot++;
  463.             break;
  464.         case '?':
  465.             usage();
  466.             exit(1);
  467.             break;
  468.         }
  469.     }
  470. }
  471.  
  472. void
  473. event_loop()
  474. {
  475.     int n;
  476.     XEvent event;
  477.  
  478.     n = XEventsQueued(dpy, QueuedAfterFlush);
  479.     while (n--) {
  480.         XNextEvent(dpy, &event);
  481.         switch(event.type) {
  482.             case KeyPress:
  483.                 Getkey(&event);
  484.                 break;
  485.             case Expose:
  486.                 redisplay(&event);
  487.                 break;
  488.             case ConfigureNotify:
  489.                 resize();
  490.                 break;
  491.         }
  492.     }
  493. }
  494.  
  495. int
  496. checkit() 
  497. {
  498.     static int i, j;
  499.  
  500.     for (i=0;i<3;i++)
  501.         for (j=0;j<3;j++)
  502.             if (xy[now_x + i - 1][now_y + j - 1])
  503.                 return(0);
  504.     return(1);
  505. }
  506.  
  507. int
  508. walk(x,y)
  509. int x,y;
  510. {
  511.     now_x = x;
  512.     now_y = y;
  513.     if (checkit() == 0)
  514.         return(1);
  515.     for(;;) {
  516.         event_loop();
  517.         now_x += (((int)lrand48()%3) - 1);
  518.         now_y--;
  519.         if ((now_y <= 0) || (now_x >= width) || (now_x <= 0))
  520.             return(0);
  521.         if (checkit() == 0)
  522.             return(1);
  523.     }
  524.     return(0);
  525. }
  526.  
  527. aggregate() 
  528. {
  529.     static int enter_x, enter_y;
  530.  
  531.     enter_x = ((int)lrand48() % (width-2)) + 1;
  532.     enter_y = (max_y > (height - 1)) ? (height - 1) : max_y;
  533.     if (walk(enter_x,enter_y)) {
  534.         count++;
  535.         max_y = (now_y > (max_y - 2)) ? now_y + 2 : max_y;
  536.         if ((count%col_duration) == 0) {
  537.            FlushBuffer(dpy,canvas,pixmap,Data_GC,&Points,coral_hue,coral_hue+1);
  538.            count=1;
  539.            coral_hue++;
  540.            if (coral_hue >= maxcolor)
  541.                 coral_hue = STARTCOLOR;
  542.         }
  543.         xy[now_x][now_y] = coral_hue;
  544.         BufferPoint(dpy, canvas, pixmap, Data_GC, &Points, coral_hue, 
  545.                     now_x, height - now_y - 1);
  546.         FlushBuffer(dpy,canvas,pixmap,Data_GC,&Points,coral_hue,coral_hue+1);
  547.     }
  548. }
  549.  
  550. main(argc,argv)
  551. int argc;
  552. char *argv[];
  553. {
  554.     static int i, j;
  555.     XSizeHints hint;
  556.     Atom __SWM_VROOT = None;
  557.     Window rootReturn, parentReturn, *children;
  558.     unsigned int numChildren;
  559.     extern void srand48(), init_color();
  560.     
  561.     parseargs(argc,argv);
  562.     dpy = XOpenDisplay("");
  563.     screen = DefaultScreen(dpy);
  564.     if (full || useroot) {
  565.         width = XDisplayWidth(dpy, screen);
  566.         height = XDisplayHeight(dpy, screen);
  567.     }
  568.     maxcolor  = (int)XDisplayCells(dpy, screen);
  569.     if (maxcolor <= 16) {
  570.         STARTCOLOR = 2; delay = 100;
  571.         INDEXINC = 1; mincolindex = 5;
  572.     }
  573.     maxcolor = Min(maxcolor, MAXCOLOR);
  574.     if (col_duration == 0)
  575.         col_duration = Min(nballs * maxcolor, 4096);
  576.     coral_hue = STARTCOLOR;
  577.     /*
  578.     * Create the pixmap to hold the coral growth
  579.     */
  580.     pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 
  581.                            DefaultDepth(dpy, screen));
  582.     /*
  583.     * Create the window to display the fractal topographic map
  584.     */
  585.     hint.x = 0;
  586.     hint.y = 0;
  587.     hint.width = width;
  588.     hint.height = height;
  589.     hint.flags = PPosition | PSize;
  590.     if (useroot) {
  591.         canvas = DefaultRootWindow(dpy);
  592.         /* search for virtual root (from ssetroot by Tom LaStrange) */
  593.         __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
  594.         XQueryTree(dpy,canvas,&rootReturn,&parentReturn,&children,&numChildren);
  595.         for (j = 0; j < numChildren; j++) {
  596.             Atom actual_type;
  597.             int actual_format;
  598.             long nitems, bytesafter;
  599.             Window *newRoot = NULL;
  600.  
  601.             if (XGetWindowProperty (dpy, children[j], __SWM_VROOT,0,1, False, 
  602.                 XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter,
  603.                 (unsigned char **) &newRoot) == Success && newRoot) {
  604.                 canvas = *newRoot;
  605.                 break;
  606.             }
  607.         }
  608.     }
  609.     else {
  610.         canvas = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  611.             0, 0, width, height, 5, 0, 1);
  612.         XSetStandardProperties(dpy, canvas, "Coral by Ron Record",
  613.             "Coral", None, argv, argc, &hint);
  614.         XMapRaised(dpy, canvas);
  615.         XSelectInput(dpy,canvas,KeyPressMask|ExposureMask|StructureNotifyMask);
  616.     }
  617.     XChangeProperty(dpy, canvas, XA_WM_CLASS, XA_STRING, 8, PropModeReplace, 
  618.                     "coral", strlen("coral"));
  619.     /*
  620.     * Create the window used to display the help info
  621.     */
  622.     if (!useroot) {
  623.         hint.x = XDisplayWidth(dpy, screen) / 4;
  624.         hint.y = XDisplayHeight(dpy, screen) / 4;
  625.         hint.width = hint.x * 2;
  626.         hint.height = hint.y * 2;
  627.         help = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  628.                 hint.x, hint.y, hint.width, hint.height, 5, 0, 1);
  629.         XSetWindowBackground(dpy, help, BlackPixel(dpy, screen));
  630.         /* Title */
  631.         XSetStandardProperties(dpy,help,"Help","Help",None,argv,argc,&hint);
  632.         XSelectInput(dpy,help,KeyPressMask|ExposureMask);
  633.         /* Try to write into a new color map */
  634.         cmap = XCreateColormap(dpy,canvas,DefaultVisual(dpy,screen),AllocAll);
  635.         init_color(dpy, canvas, cmap, Colors, STARTCOLOR, mincolindex, maxcolor,
  636.                     numwheels,"coral", "Coral", 0);
  637.         /* install new color map */
  638.         XSetWindowColormap(dpy, canvas, cmap);
  639.         XSetWindowColormap(dpy, help, cmap);
  640.     }
  641.     init_contexts();
  642.     setupmem();
  643.     Clear();
  644.     srand48((long)time(0));
  645.     for (i=0; i!=nummaps; i++) {
  646.         next = 0;
  647.         InitBuffer(&Points, maxcolor);
  648.         init_pts();
  649.         for (;;) {
  650.             event_loop();
  651.             aggregate();
  652.             if (now_y >= (height - 1))
  653.                 break;
  654.         }
  655.         FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  656.         if (oflag)
  657.             save();
  658.         if (demo) {
  659.             event_loop();
  660.             DemoSpin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 4);
  661.             event_loop();
  662.             for (j=0; j<=MAXWHEELS; j++) {
  663.                 init_color(dpy, canvas, cmap, Colors, STARTCOLOR, mincolindex, 
  664.                         maxcolor, i, "coral", "Coral", 0);
  665.                 event_loop();
  666.                 sleep(1);
  667.             }
  668.         }
  669.         else if (useroot) {
  670.             XSetWindowBackgroundPixmap(dpy, canvas, pixmap);
  671.             XFreePixmap(dpy, pixmap);
  672.             XClearWindow(dpy, canvas);
  673.             XFlush(dpy);
  674.             Cleanup();
  675.             exit(0);
  676.         }
  677.         else {
  678.             XSync(dpy, True);
  679.             if (spin)
  680.                 Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 0);
  681.             for (;;) {
  682.                 event_loop();
  683.                 if (next) break;
  684.             }
  685.         }
  686.     }
  687.     Cleanup();
  688.     exit(0);
  689. }
  690.